#pragma once

#include <cftc/reflect/object.h>
#include <cftf/meta/table.h>

namespace dbc
{
#if 1
    struct TalentSpellPos
    {
        TalentSpellPos() : talent_id(0), rank(0) {}
        TalentSpellPos(unsigned short _talent_id, unsigned char _rank) : talent_id(_talent_id), rank(_rank) {}

        unsigned short talent_id = 0;
        unsigned char  rank = 0;
    };
#endif

    class AreaTableEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int  ID = 0;                                             // 0        m_ID - ID of the Area within the DBC.
        unsigned int  mapid = 0;                                          // 1        m_ContinentID - ID of the Continent in DBC (0 = Azeroth, 1 = Kalimdor, ...)
        unsigned int  zone = 0;                                           // 2        m_ParentAreaID - ID of the parent area.
        unsigned int  exploreFlag = 0;                                    // 3        m_AreaBit -
        unsigned int  flags = 0;                                          // 4        m_flags -
        // 5        m_SoundProviderPref
        // 6        m_SoundProviderPrefUnderwater
        // 7        m_AmbienceID
        // 8        m_ZoneMusic
        // 9        m_IntroSound
        int   area_level = 0;                                     // 10       m_ExplorationLevel - Level of Area, used for XP reward calculation.
        char* area_name[8] = { 0 };                                   // 11-18    m_AreaName_lang - Area Name, position is relying on locale.
        // 19 string flags
        unsigned int  team = 0;                                           // 20       m_factionGroupMask - Define the faction owning the area (see AreaTeams for values).
        // 21-23    uknown/unused
        unsigned int  LiquidTypeOverride = 0;                             // 24       m_liquidTypeID - Override for water type (only used for Naxxramass ATM).
    };

    class AreaTriggerEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    id = 0;                                           // 0 - ID of the Area within the DBC.
        unsigned int    mapid = 0;                                        // 1 - ID of the Continent in DBC (0 = Azeroth, 1 = Kalimdor, ...)
        float     x = 0;                                            // 2 - X position of the Area Trigger Entry.
        float     y = 0;                                            // 3 - Y position of the Area Trigger Entry.
        float     z = 0;                                            // 4 - Z position of the Area Trigger Entry.
        float     radius = 0;                                       // 5 - Radius around the Area Trigger point.
        float     box_x = 0;                                        // 6 - extent x edge
        float     box_y = 0;                                        // 7 - extent y edge
        float     box_z = 0;                                        // 8 - extent z edge
        float     box_orientation = 0;                              // 9 - extent rotation by about z axis
    };

    class AuctionHouseEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    houseId = 0;                                      // 0        m_ID - ID of the Auction House in the DBC.
        unsigned int    faction = 0;                                      // 1        m_factionID - ID of the Faction (see faction.dbc).
        unsigned int    depositPercent = 0;                               // 2        m_depositRate - Percentage taken for any deposit.
        unsigned int   cutPercent = 0;                                   // 3        m_consignmentRate - Percentage taken for any sell.
        // char*     name[8];                                   // 4-11     m_name_lang
        // 12 string flags
    };

    class BankBagSlotPricesEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int  ID = 0;                                             // 0        m_ID - ID of the Bank Bag Slot in the DBC.
        unsigned int  price = 0;                                        // 1        m_Cost - Price of the Bank Bag Slot.
    };

#define MAX_OUTFIT_ITEMS 12

    /**
    * \struct CharStartOutfitEntry
    * \brief
    *
    */
    class CharStartOutfitEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        // unsigned int Id;                                           // 0        m_ID
        unsigned int RaceClassGender = 0;                                 // 1        m_raceID m_classID m_sexID m_outfitID (UNIT_FIELD_BYTES_0 & 0x00FFFFFF) comparable (0 byte = race, 1 byte = class, 2 byte = gender)
        int ItemId[MAX_OUTFIT_ITEMS] = { 0 };                         // 2-13     m_ItemID
        // int ItemDisplayId[MAX_OUTFIT_ITEMS];               // 14-25    m_DisplayItemID not required at server side
        // int ItemInventorySlot[MAX_OUTFIT_ITEMS];           // 26-37    m_InventoryType not required at server side
        // unsigned int Unknown1;                                     // 38, unique values (index-like with gaps ordered in other way as ids)
        // unsigned int Unknown2;                                     // 39
        // unsigned int Unknown3;                                     // 40
    };


    class ChatChannelsEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int  ChannelID = 0;                                      // 0        m_ID - ID of the Channel in DBC.
        unsigned int  flags = 0;                                          // 1        m_flags - Flags indicating the type of channel (trading, guid recruitment, ...).
        // 2        m_factionGroup
        char const* pattern[8] = { 0 };                               // 3-10     m_name_lang - Channel Name (using locales).
        // 11 string flags
        // char*       name[8];                                 // 12-19    m_shortcut_lang
        // 20 string flag
    };

    class ChrClassesEntry : public cftc::reflect::Object, public cftf::meta::Table<ChrClassesEntry, unsigned int>
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int  ClassID = 0;                                        // 0        m_ID - ID of the Char Class in DBC.
        // unsigned int unk1;                                         // 1 unknown, all 1
        // unsigned int flags;                                        // 2 unknown
        unsigned int  powerType = 0;                                      // 3        m_DisplayPower - Power Type, (1 = Rage, 3 = Energy, 0 = Mana).
        // 4        m_petNameToken
        //char const* name[8] = { 0 };                                    // 5-12     m_name_lang - Class Name (using locales).
        std::vector<std::string> name;                                    // 5-12     m_name_lang - Class Name (using locales).
        // 13 string flags
        // 14       m_filename
        unsigned int  spellfamily = 0;                                    // 15       m_spellClassSet - Spell Class ID (3 = Mage, 4 = Warrior, 5 = Warlock, ...)
        // unsigned int flags2;                                       // 16       m_flags (0x1 HasRelicSlot)
    };

    class ChrRacesEntry : public cftc::reflect::Object, public cftf::meta::Table<ChrRacesEntry, unsigned int>
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int      RaceID = 0;                                     // 0        m_ID - ID of the Char Race in DBC.
        // 1        m_flags
        unsigned int      FactionID = 0;                                  // 2        m_factionID - ID of the faction in DBC. (See Faction.dbc)
        // 3        m_ExplorationSoundID
        unsigned int      model_m = 0;                                    // 4        m_MaleDisplayId - ID of the Male Display.
        unsigned int      model_f = 0;                                    // 5        m_FemaleDisplayId - ID of the Female Display.
        // 6        m_ClientPrefix
        // 7        unused
        unsigned int      TeamID = 0;                                     // 8        m_BaseLanguage - ID of the Major Playable Faction (7-Alliance 1-Horde).
        // 9        m_creatureType
        // 10       unused, all 836
        // 11       unused, all 1604
        // 12       m_ResSicknessSpellID
        // 13       m_SplashSoundID
        unsigned int      startingTaxiMask = 0;                           // 14        Starting Taxi Max for the given Race (already discovered Taxi Nodes).
        // 15       m_clientFileString
        unsigned int      CinematicSequence = 0;                          // 16       m_cinematicSequenceID - Cinematic Sequence ID.
        std::vector<std::string> name;                                    // 17-24    m_name_lang used for DBC language detection/selection
        // 25 string flags
        // 26-27    m_facialHairCustomization[2]
        // 28       m_hairCustomization
    };

    class CinematicSequencesEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int      Id = 0;                                         // 0        m_ID - ID in DBC.
        // unsigned int      unk1;                                    // 1        m_soundID
        // unsigned int      cinematicCamera;                         // 2        m_camera[8]
    };

    class CreatureDisplayInfoEntry : public cftc::reflect::Object, public cftf::meta::Table<CreatureDisplayInfoEntry, unsigned int>
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int      Displayid = 0;                                  // 0        m_ID - ID in DBC.
        // 1        m_modelID
        // 2        m_soundID
        unsigned int      ExtendedDisplayInfoID = 0;                      // 3        m_extendedDisplayInfoID - Extended info (see CreatureDisplayInfoExtraEntry).
        float       scale = 0;                                      // 4        m_creatureModelScale - Scale of the Creature.
        // 5        m_creatureModelAlpha
        // 6-8      m_textureVariation[3]
        // 9        m_portraitTextureName
        // 10       m_bloodID
        // 11       m_NPCSoundID
    };

    class CreatureDisplayInfoExtraEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int      DisplayExtraId = 0;                             // 0        m_ID - ID in DBC.
        unsigned int      Race = 0;                                       // 1        m_DisplayRaceID - Race to which it's applicable.
        // unsigned int    Gender;                                    // 2        m_DisplaySexID
        // unsigned int    SkinColor;                                 // 3        m_SkinID
        // unsigned int    FaceType;                                  // 4        m_FaceID
        // unsigned int    HairType;                                  // 5        m_HairStyleID
        // unsigned int    HairStyle;                                 // 6        m_HairColorID
        // unsigned int    BeardStyle;                                // 7        m_FacialHairID
        // unsigned int    Equipment[10];                             // 8-17     m_NPCItemDisplay equipped static items EQUIPMENT_SLOT_HEAD..EQUIPMENT_SLOT_HANDS, client show its by self
        // char*                                                // 18       m_BakeName CreatureDisplayExtra-*.blp
    };

    class CreatureFamilyEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    ID = 0;                                           // 0 - ID in DBC.
        float     minScale = 0;                                     // 1 - Min Scale of creature within the game.
        unsigned int    minScaleLevel = 0;                                // 2 0/1 - Minimum level for which the minScale is applicable.
        float     maxScale = 0;                                     // 3 - Max Scale of creature within the game.
        unsigned int    maxScaleLevel = 0;                                // 4 0/60 - Maximum level for which the maxScale is applicable.
        unsigned int    skillLine[2] = { 0 };                                 // 5-6 - Skill Lines (See SkillLine.dbc).
        unsigned int    petFoodMask = 0;                                  // 7 - Food Mask for the given pet.
        char* Name[8] = { 0 };
    };

#define MAX_CREATURE_SPELL_DATA_SLOT 4

    /**
    * \struct CreatureSpellDataEntry
    * \brief Entry representing the different spell available for player's pet.
    */
    class CreatureSpellDataEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    ID;                                           // 0        m_ID - ID in DBC.
        unsigned int    spellId[MAX_CREATURE_SPELL_DATA_SLOT];        // 1-4      m_spells[4] - Spell ID's (see Spell.dbc).
        // unsigned int    availability[MAX_CREATURE_SPELL_DATA_SLOT];// 4-7      m_availability[4]
    };

    class CreatureTypeEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    ID;                                           // 0        m_ID
        // char*   Name[8];                                     // 1-8      m_name_lang
        // 9 string flags
        // unsigned int    no_expirience;                             // 10       m_flags
    };

    class DurabilityCostsEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    Itemlvl = 0;                                      // 0        m_ID - ID in DBC.
        unsigned int    multiplier[29] = { 0 };                               // 1-29     m_weaponSubClassCost m_armorSubClassCost
    };

    class DurabilityQualityEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    Id = 0;                                           // 0        m_ID - ID in DBC.
        float     quality_mod = 0;                                  // 1        m_data - Quality modifier values.
    };

    class EmotesEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int  Id = 0;                                             // 0        m_ID - ID in DBC.
        // char*   Name;                                        // 1        m_EmoteSlashCommand
        // unsigned int  AnimationId;                                 // 2        m_AnimID
        //unsigned int  Flags;                                          // 3        m_EmoteFlags
        unsigned int  EmoteType = 0;                                      // 4        m_EmoteSpecProc (determine how emote are shown)
        //unsigned int  UnitStandState;                                 // 5        m_EmoteSpecProcParam
        // unsigned int  SoundId;                                     // 6        m_EventSoundID
    };

    class EmotesTextEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int  Id = 0;                                             //          m_ID - ID in DBC.
        //          m_name
        unsigned int  textid = 0;                                         //          m_emoteID - ID of the text.
        //          m_emoteText
    };

    class FactionEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int      ID = 0;                                         // 0        m_ID - ID in DBC.
        int       reputationListID = 0;                           // 1        m_reputationIndex - ID of the Reputation List.
        unsigned int      BaseRepRaceMask[4] = { 0 };                         // 2-5      m_reputationRaceMask -
        unsigned int      BaseRepClassMask[4] = { 0 };                        // 6-9      m_reputationClassMask
        int       BaseRepValue[4] = { 0 };                            // 10-13    m_reputationBase
        unsigned int      ReputationFlags[4] = { 0 };                         // 14-17    m_reputationFlags
        unsigned int      team = 0;                                       // 18       m_parentFactionID
        char* name[8] = { 0 };                                    // 19-26    m_name_lang
        // 27 string flags
        // char*     description[8];                            // 28-35    m_description_lang
        // 36 string flags

        // helpers

        int GetIndexFitTo(unsigned int raceMask, unsigned int classMask) const
        {
            for (int i = 0; i < 4; ++i)
            {
                if ((BaseRepRaceMask[i] == 0 || (BaseRepRaceMask[i] & raceMask)) &&
                    (BaseRepClassMask[i] == 0 || (BaseRepClassMask[i] & classMask)))
                {
                    return i;
                }
            }

            return -1;
        }
    };

    class FactionTemplateEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        /// 0
        unsigned int      ID = 0;
        /// 1
        unsigned int      faction = 0;
        /// 2 specific flags for that faction
        unsigned int      factionFlags = 0;
        /// 3 if mask set (see FactionMasks) then faction included in masked team
        unsigned int      ourMask = 0;
        /// 4 if mask set (see FactionMasks) then faction friendly to masked team
        unsigned int      friendlyMask = 0;
        /// 5 if mask set (see FactionMasks) then faction hostile to masked team
        unsigned int      hostileMask = 0;
        /// 6-9
        unsigned int      enemyFaction[4] = { 0 };
        /// 10-13
        unsigned int      friendFaction[4] = { 0 };
        //-------------------------------------------------------  end structure

        // helpers
        bool IsFriendlyTo(FactionTemplateEntry const& entry) const
        {
            if (entry.faction)
            {
                for (int i = 0; i < 4; ++i)
                    if (enemyFaction[i] == entry.faction)
                    {
                        return false;
                    }
                for (int i = 0; i < 4; ++i)
                    if (friendFaction[i] == entry.faction)
                    {
                        return true;
                    }
            }
            return (friendlyMask & entry.ourMask) || (ourMask & entry.friendlyMask);
        }
        bool IsHostileTo(FactionTemplateEntry const& entry) const
        {
            if (entry.faction)
            {
                for (int i = 0; i < 4; ++i)
                    if (enemyFaction[i] == entry.faction)
                    {
                        return true;
                    }
                for (int i = 0; i < 4; ++i)
                    if (friendFaction[i] == entry.faction)
                    {
                        return false;
                    }
            }
            return (hostileMask & entry.ourMask) != 0;
        }
        bool IsHostileToPlayers() const { return (hostileMask & FACTION_MASK_PLAYER) != 0; }
        bool IsNeutralToAll() const
        {
            for (int i = 0; i < 4; ++i)
                if (enemyFaction[i] != 0)
                {
                    return false;
                }
            return hostileMask == 0 && friendlyMask == 0;
        }
        bool IsContestedGuardFaction() const { return (factionFlags & FACTION_TEMPLATE_FLAG_CONTESTED_GUARD) != 0; }
    };

    class GameObjectDisplayInfoEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int      Displayid = 0;                                  // 0        m_ID - ID in DBC.
        char* filename = nullptr;                                   // 1        m_modelName - File name for  the object.
        // unsigned int   m_Sound[10];                                // 2-11     m_Sound
    };

    class ItemBagFamilyEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int   ID = 0;                                            // 0        m_ID
        // char*     name[8]                                    // 1-8      m_name_lang
        //                                                      // 9        name flags
    };


    class ItemClassEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int   ID = 0;                                            // 0        m_ID
        // unsigned int   unk1;                                       // 1
        // unsigned int   unk2;                                       // 2        only weapon have 1 in field, other 0
        char* name[8] = { 0 };                                       // 3-11     m_name_lang
        //                                                      // 12       name flags
    };

    class ItemRandomPropertiesEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    ID = 0;                                           // 0        m_ID
        // char*     internalName                               // 1        m_Name
        unsigned int    enchant_id[3] = { 0 };                                // 2-4      m_Enchantment
        // 5-6 unused, 0 only values, reserved for additional enchantments
        // char*     nameSuffix[8];                             // 7-14     m_name_lang
        // 15 string flags
    };

    class ItemSetEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        // unsigned int    id                                         // 0        m_ID
        char* name[8] = { 0 };                                      // 1-8      m_name_lang
        // 9 string flags
        // unsigned int    itemId[17];                                // 10-26    m_itemID
        unsigned int    spells[8] = { 0 };                                    // 27-34    m_setSpellID
        unsigned int    items_to_triggerspell[8] = { 0 };                     // 35-42    m_setThreshold
        unsigned int    required_skill_id = 0;                            // 43       m_requiredSkill
        unsigned int    required_skill_value = 0;                         // 44       m_requiredSkillRank
    };

    class LiquidTypeEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int Id = 0;                                              // 0
        unsigned int LiquidId = 0;                                        // 1        23: Water; 29: Ocean; 35: Magma; 41: Slime; 47: Naxxramas - Slime.
        unsigned int Type = 0;                                            // 2        0: Magma; 2: Slime; 3: Water.
        unsigned int SpellId = 0;                                         // 3        Reference to Spell.dbc
    };

#define MAX_LOCK_CASE 8

    /**
    * \struct LockEntry
    * \brief Entry representing the different "locks" existing in game (chest, veins, herbs, ...).
    */
    class LockEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int      ID = 0;                                         // 0        m_ID
        unsigned int      Type[MAX_LOCK_CASE] = { 0 };                        // 1-5      m_Type
        unsigned int      Index[MAX_LOCK_CASE] = { 0 };                       // 9-16     m_Index
        unsigned int      Skill[MAX_LOCK_CASE] = { 0 };                       // 17-24    m_Skill
        // unsigned int      Action[MAX_LOCK_CASE];                   // 25-32    m_Action
    };

    class MailTemplateEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int      ID = 0;                                         // 0        m_ID
        // char*       subject[8];                              // 1-8      m_subject_lang
        // 9 string flags
    };

    class MapEntry : public cftc::reflect::Object, public cftf::meta::Table<MapEntry, unsigned int>
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        static const int NAME_SIZE = 8;
        unsigned int  MapID = 0;                                          // 0        m_ID
        // char*       internalname;                            // 1        m_Directory
        unsigned int  map_type = 0;                                       // 2        m_InstanceType
        // unsigned int isPvP;                                        // 3        m_PVP 0 or 1 for battlegrounds (not arenas)
#if 1
        std::vector<std::string> name;
#else
        char* name[8] = { 0 };                                        // 4-11     m_MapName_lang
#endif
        // 12 string flags
        // 13-15 unused (something PvPZone related - levels?)
        // 16-18
        unsigned int  linked_zone = 0;                                    // 19       m_areaTableID
        // char*     hordeIntro[8];                             // 20-27    m_MapDescription0_lang
        // 28 string flags
        // char*     allianceIntro[8];                          // 29-36    m_MapDescription1_lang
        // 37 string flags
        unsigned int  multimap_id = 0;                                    // 38       m_LoadingScreenID (LoadingScreens.dbc)
        // 39-40 not used
        // float   BattlefieldMapIconScale;                     // 41       m_minimapIconScale

        // Helpers

        bool IsDungeon() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID; }
        bool IsNonRaidDungeon() const { return map_type == MAP_INSTANCE; }
        bool Instanceable() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID || map_type == MAP_BATTLEGROUND; }
        bool IsRaid() const { return map_type == MAP_RAID; }
        bool IsBattleGround() const { return map_type == MAP_BATTLEGROUND; }

        bool IsMountAllowed() const
        {
            return !IsDungeon() ||
                MapID == 309 || MapID == 209 || MapID == 509 || MapID == 269;
        }

        bool IsContinent() const
        {
            return MapID == 0 || MapID == 1;
        }
    };

    class MovieEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int      Id = 0;                                         // 0        m_ID
        // char*       filename;                                // 1        m_filename
        // unsigned int      unk2;                                    // 2        m_volume
    };

    class QuestSortEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int      id = 0;                                         // 0        m_ID
        // char*       name[8];                                 // 1-8      m_SortName_lang
        // 9 string flags
    };

    class SkillRaceClassInfoEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        // unsigned int    id;                                        // 0        m_ID
        unsigned int    skillId = 0;                                      // 1        m_skillID
        unsigned int    raceMask = 0;                                     // 2        m_raceMask
        unsigned int    classMask = 0;                                    // 3        m_classMask
        unsigned int    flags = 0;                                        // 4        m_flags
        unsigned int    reqLevel = 0;                                     // 5        m_minLevel
        // unsigned int    skillTierId;                               // 6        m_skillTierID
        // unsigned int    skillCostID;                               // 7        m_skillCostIndex
    };

    class SkillLineEntry : public cftc::reflect::Object, public cftf::meta::Table<SkillLineEntry, unsigned int>
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    id = 0;                                           // 0        m_ID
        int     categoryId = 0;                                   // 1        m_categoryID
        // unsigned int    skillCostID;                               // 2        m_skillCostsID
        //char* name[8] = { 0 };                                      // 3-10     m_displayName_lang
        std::vector<std::string> name;                                      // 3-10     m_displayName_lang
        // 11 string flags
        // char*     description[8];                            // 12-19    m_description_lang
        // 20 string flags
        // unsigned int    spellIcon;                                    // 21       m_spellIconID
        SkillRangeType GetSkillRangeType(bool racial) const;
        static bool IsProfessionSkill(unsigned int skill);
        static bool IsPrimaryProfessionSkill(unsigned int skill);
    };

    class SkillLineAbilityEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    id = 0;                                           // 0, INDEX
        unsigned int    skillId = 0;                                      // 1
        unsigned int    spellId = 0;                                      // 2
        unsigned int    racemask = 0;                                     // 3
        unsigned int    classmask = 0;                                    // 4
        // unsigned int    racemaskNot;                               // 5 always 0 in 2.4.2
        // unsigned int    classmaskNot;                              // 6 always 0 in 2.4.2
        unsigned int    req_skill_value = 0;                              // 7 for trade skill.not for training.
        unsigned int    forward_spellid = 0;                              // 8
        unsigned int    learnOnGetSkill = 0;                              // 9 can be 1 or 2 for spells learned on get skill
        unsigned int    max_value = 0;                                    // 10
        unsigned int    min_value = 0;                                    // 11
        // 12-13, unknown, always 0
        unsigned int    reqtrainpoints = 0;                               // 14
    };

    class SoundEntriesEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    Id = 0;                                           // 0        m_ID
        // unsigned int    Type;                                      // 1        m_soundType
        // char*     InternalName;                              // 2        m_name
        // char*     FileName[10];                              // 3-12     m_File[10]
        // unsigned int    Unk13[10];                                 // 13-22    m_Freq[10]
        // char*     Path;                                      // 23       m_DirectoryBase
        // 24       m_volumeFloat
        // 25       m_flags
        // 26       m_minDistance
        // 27       m_distanceCutoff
        // 28       m_EAXDef
    };

    class ClassFamilyMask : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        // Flags of the class family.
        unsigned long long Flags = 0;

        /**
        * Default constructor.
        */
        ClassFamilyMask() : Flags(0) {}

        /**
        * Constructor taking familyFlags as parameter.
        */
        explicit ClassFamilyMask(unsigned long long familyFlags) : Flags(familyFlags) {}

        /**
        * function indicating whether the class is empty ( = 0) or not.
        * Returns a boolean value.
        */
        bool Empty() const { return Flags == 0; }

        /**
        * function overloading the operator !
        * Returns a boolean value.
        */
        bool operator!() const { return Empty(); }

        operator void const* () const { return Empty() ? NULL : this; } // for allow normal use in if(mask)

        /**
        * function indicating whether a familyFlags belongs to a Spell Family.
        * Does a bitwise comparison between current Flags and familyFlags given in parameter.
        * Returns a boolean value.
        * \param familyFlags The familyFlags to compare.
        */
        bool IsFitToFamilyMask(unsigned long long familyFlags) const
        {
            return Flags & familyFlags;
        }

        /**
        * function indicating whether a ClassFamilyMask belongs to a Spell Family.
        * Does a bitwise comparison between current Flags and mask's flags.
        * Returns a boolean value.
        * \param mask The ClassFamilyMask to compare.
        */
        bool IsFitToFamilyMask(ClassFamilyMask const& mask) const
        {
            return Flags & mask.Flags;
        }

        /**
        * function overloading the operator & for bitwise comparison.
        */
        unsigned long long operator& (unsigned long long mask) const                    // possible will removed at finish convertion code use IsFitToFamilyMask
        {
            return Flags & mask;
        }

        /**
        * function overloading operator |=.
        */
        ClassFamilyMask& operator|= (ClassFamilyMask const& mask)
        {
            Flags |= mask.Flags;
            return *this;
        }
    };
    
#define MAX_SPELL_REAGENTS 8
#define MAX_SPELL_TOTEMS 2

    /**
    * \struct SpellEntry
    * \brief Entry representing each spell of the game.
    *
    * This structure also contains flags about spell family, attributes, spell effects
    * enchantement, cast conditions, proc conditions, mechanic, cast time, damage range, ...
    *
    * All we need to know about spells is represented by such entry and used for every effect within the game
    * such as elixir, potion, buff, heal, damage, ..
    */
    class SpellEntry : public cftc::reflect::Object, public cftf::meta::Table<SpellEntry, unsigned int>
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    Id = 0;                                       // 0 normally counted from 0 field (but some tools start counting from 1, check this before tool use for data view!)
        unsigned int    School = 0;                                   // 1 not schoolMask from 2.x - just school type so everything linked with SpellEntry::SchoolMask must be rewrited
        unsigned int    Category = 0;                                 // 2
        // unsigned int castUI;                                   // 3 not used
        unsigned int    Dispel = 0;                                   // 4
        unsigned int    Mechanic = 0;                                 // 5
        unsigned int    Attributes = 0;                               // 6
        unsigned int    AttributesEx = 0;                             // 7
        unsigned int    AttributesEx2 = 0;                            // 8
        unsigned int    AttributesEx3 = 0;                            // 9
        unsigned int    AttributesEx4 = 0;                            // 10
        unsigned int    Stances = 0;                                  // 11
        unsigned int    StancesNot = 0;                               // 12
        unsigned int    Targets = 0;                                  // 13
        unsigned int    TargetCreatureType = 0;                       // 14
        unsigned int    RequiresSpellFocus = 0;                       // 15
        unsigned int    CasterAuraState = 0;                          // 16
        unsigned int    TargetAuraState = 0;                          // 17
        unsigned int    CastingTimeIndex = 0;                         // 18
        unsigned int    RecoveryTime = 0;                             // 19
        unsigned int    CategoryRecoveryTime = 0;                     // 20
        unsigned int    InterruptFlags = 0;                           // 21
        unsigned int    AuraInterruptFlags = 0;                       // 22
        unsigned int    ChannelInterruptFlags = 0;                    // 23
        unsigned int    procFlags = 0;                                // 24
        unsigned int    procChance = 0;                               // 25
        unsigned int    procCharges = 0;                              // 26
        unsigned int    maxLevel = 0;                                 // 27
        unsigned int    baseLevel = 0;                                // 28
        unsigned int    spellLevel = 0;                               // 29
        unsigned int    DurationIndex = 0;                            // 30
        unsigned int    powerType = 0;                                // 31
        unsigned int    manaCost = 0;                                 // 32
        unsigned int    manaCostPerlevel = 0;                         // 33
        unsigned int    manaPerSecond = 0;                            // 34
        unsigned int    manaPerSecondPerLevel = 0;                    // 35
        unsigned int    rangeIndex = 0;                               // 36
        float     speed = 0;                                    // 37
        unsigned int    modalNextSpell = 0;                           // 38 not used
        unsigned int    StackAmount = 0;                              // 39
        //unsigned int    Totem[MAX_SPELL_TOTEMS] = {0};                  // 40-41
        std::vector<unsigned int>    Totem;                  // 40-41
        //int     Reagent[MAX_SPELL_REAGENTS] = {0};              // 42-49
        std::vector<int>     Reagent;              // 42-49
        //unsigned int    ReagentCount[MAX_SPELL_REAGENTS] = {0};         // 50-57
        std::vector<unsigned int>    ReagentCount;         // 50-57
        int     EquippedItemClass = 0;                        // 58 (value)
        int     EquippedItemSubClassMask = 0;                 // 59 (mask)
        int     EquippedItemInventoryTypeMask = 0;            // 60 (mask)
        //unsigned int    Effect[MAX_EFFECT_INDEX] = {0};                 ///< 61-63 TODO DOCUMENT
        std::vector<unsigned int>    Effect;                 ///< 61-63 TODO DOCUMENT
        //int     EffectDieSides[MAX_EFFECT_INDEX] = {0};         // 64-66
        std::vector<int>     EffectDieSides;         // 64-66
        //unsigned int    EffectBaseDice[MAX_EFFECT_INDEX] = {0};         // 67-69
        std::vector<unsigned int>    EffectBaseDice;         // 67-69
        //float     EffectDicePerLevel[MAX_EFFECT_INDEX] = {0};     // 70-72
        std::vector<float>     EffectDicePerLevel;     // 70-72
        //float     EffectRealPointsPerLevel[MAX_EFFECT_INDEX] = {0};   // 73-75
        std::vector<float>     EffectRealPointsPerLevel;   // 73-75
        //int     EffectBasePoints[MAX_EFFECT_INDEX] = {0};       // 76-78 (don't must be used in spell/auras explicitly, must be used cached Spell::m_currentBasePoints)
        std::vector<int>     EffectBasePoints;       // 76-78 (don't must be used in spell/auras explicitly, must be used cached Spell::m_currentBasePoints)
        //unsigned int    EffectMechanic[MAX_EFFECT_INDEX] = {0};         // 79-81
        std::vector<unsigned int>    EffectMechanic;         // 79-81
        //unsigned int    EffectImplicitTargetA[MAX_EFFECT_INDEX] = {0};  // 82-84
        std::vector<unsigned int>    EffectImplicitTargetA;  // 82-84
        //unsigned int    EffectImplicitTargetB[MAX_EFFECT_INDEX] = {0};  // 85-87
        std::vector<unsigned int>    EffectImplicitTargetB;  // 85-87
        //unsigned int    EffectRadiusIndex[MAX_EFFECT_INDEX] = {0};      // 88-90 - spellradius.dbc
        std::vector<unsigned int>    EffectRadiusIndex;      // 88-90 - spellradius.dbc
        //unsigned int    EffectApplyAuraName[MAX_EFFECT_INDEX] = {0};    // 91-93
        std::vector<unsigned int>    EffectApplyAuraName;    // 91-93
        //unsigned int    EffectAmplitude[MAX_EFFECT_INDEX] = {0};        // 94-96
        std::vector<unsigned int>    EffectAmplitude;        // 94-96
        //float     EffectMultipleValue[MAX_EFFECT_INDEX] = {0};    // 97-99
        std::vector<float>     EffectMultipleValue;    // 97-99
        //unsigned int    EffectChainTarget[MAX_EFFECT_INDEX] = {0};      // 100-102
        std::vector<unsigned int>    EffectChainTarget;      // 100-102
        //unsigned int    EffectItemType[MAX_EFFECT_INDEX] = {0};         // 103-105
        std::vector<unsigned int>    EffectItemType;         // 103-105
        //int     EffectMiscValue[MAX_EFFECT_INDEX] = {};        // 106-108
        std::vector<int>     EffectMiscValue;        // 106-108
        //unsigned int    EffectTriggerSpell[MAX_EFFECT_INDEX] = {0};     // 109-111
        std::vector<unsigned int>    EffectTriggerSpell;     // 109-111
        //float     EffectPointsPerComboPoint[MAX_EFFECT_INDEX] = {0};  // 112-114
        std::vector<float>     EffectPointsPerComboPoint;  // 112-114
        unsigned int    SpellVisual = 0;                              // 115
        // unsigned int    SpellVisual2                           // 116 not used
        unsigned int    SpellIconID = 0;                              // 117
        unsigned int    activeIconID = 0;                             // 118
        // unsigned int    spellPriority;                         // 119
        //char* SpellName[8] = {0};                             // 120-127
        std::vector<std::string> SpellName;                             // 120-127
        // unsigned int    SpellNameFlag;                         // 128
        //char* Rank[8] = {0};                                  // 129-136
        std::vector<std::string> Rank;                                  // 129-136
        // unsigned int    RankFlags;                             // 137
        // char*     Description[8];                        // 138-145 not used
        // unsigned int    DescriptionFlags;                      // 146     not used
        // char*     ToolTip[8];                            // 147-154 not used
        // unsigned int    ToolTipFlags;                          // 155     not used
        unsigned int    ManaCostPercentage = 0;                       // 156
        unsigned int    StartRecoveryCategory = 0;                    // 157
        unsigned int    StartRecoveryTime = 0;                        // 158
        unsigned int    MaxTargetLevel = 0;                           // 159
        unsigned int    SpellFamilyName = 0;                          // 160
        ClassFamilyMask SpellFamilyFlags;                   // 161+162
        unsigned int    MaxAffectedTargets = 0;                       // 163
        unsigned int    DmgClass = 0;                                 // 164 defenseType
        unsigned int    PreventionType = 0;                           // 165
        // unsigned int    StanceBarOrder;                        // 166 not used
        //float     DmgMultiplier[MAX_EFFECT_INDEX] = {0};          // 167-169
        std::vector<float>     DmgMultiplier;          // 167-169
        // unsigned int    MinFactionId;                          // 170 not used, and 0 in 2.4.2
        // unsigned int    MinReputation;                         // 171 not used, and 0 in 2.4.2
        // unsigned int    RequiredAuraVision;                    // 172 not used

        /**
        * function calculating the basic damage/snare/... points for a given Spell Effect.
        * Returns an int value representing the basic points.
        * \param eff INDEX of the Spell Effect.
        */
        int CalculateSimpleValue(SpellEffectIndex eff) const { return EffectBasePoints[eff] + int(EffectBaseDice[eff]); }

        /**
        * function indicating whether a spell fits to a spell family.
        * Returns a bool value.
        * \param familyFlags The unsigned long long value of Spell Family Flags.
        */
        bool IsFitToFamilyMask(unsigned long long familyFlags) const
        {
            return SpellFamilyFlags.IsFitToFamilyMask(familyFlags);
        }

        /**
        * function indicating whether a spell fits to a spell family based on arguments.
        * Returns a bool value.
        * \param family SpellFamily to which the spell should belong to.
        * \param familyFlags The unsigned long long value of Spell Family Flags.
        */
        bool IsFitToFamily(SpellFamily family, unsigned long long familyFlags) const
        {
            return SpellFamily(SpellFamilyName) == family && IsFitToFamilyMask(familyFlags);
        }

        /**
        * function indicating whether a spell fits to a spell class family based on a ClassFamilyMask.
        * Returns a bool value.
        * \param mask ClassFamilyMask representing the class family.
        */
        bool IsFitToFamilyMask(ClassFamilyMask const& mask) const
        {
            return SpellFamilyFlags.IsFitToFamilyMask(mask);
        }

        /**
        * function indicating whether a spell fits to a spell class family based on arguments.
        * Returns a bool value.
        * \param family SpellFamily to which the spell should belong to.
        * \param masl ClassFamilyMask representing the class family.
        */
        bool IsFitToFamily(SpellFamily family, ClassFamilyMask const& mask) const
        {
            return SpellFamily(SpellFamilyName) == family && IsFitToFamilyMask(mask);
        }

        /**
        * function indicating whether a spell has an attribute doing bitwise comparison.
        * Returns a bool value.
        * \param attribute SpellAttributes to compare to actual attribute.
        */
        inline bool HasAttribute(SpellAttributes attribute) const { return Attributes & attribute; }

        /**
        * function indicating whether a spell has an attribute doing bitwise comparison.
        * Returns a bool value.
        * \param attribute SpellAttributesEx to compare to actual attributeEx.
        */
        inline bool HasAttribute(SpellAttributesEx attribute) const { return AttributesEx & attribute; }

        /**
        * function indicating whether a spell has an attribute doing bitwise comparison.
        * Returns a bool value.
        * \param attribute SpellAttributesEx2 to compare to actual attributeEx2.
        */
        inline bool HasAttribute(SpellAttributesEx2 attribute) const { return AttributesEx2 & attribute; }

        /**
        * function indicating whether a spell has an attribute doing bitwise comparison.
        * Returns a bool value.
        * \param attribute SpellAttributesEx3 to compare to actual attributeEx3.
        */
        inline bool HasAttribute(SpellAttributesEx3 attribute) const { return AttributesEx3 & attribute; }

        /**
        * function indicating whether a spell has an attribute doing bitwise comparison.
        * Returns a bool value.
        * \param attribute SpellAttributesEx4 to compare to actual attributeEx4.
        */
        inline bool HasAttribute(SpellAttributesEx4 attribute) const { return AttributesEx4 & attribute; }

        inline bool HasSpellEffect(SpellEffects effect) const
        {
            for (unsigned char i = EFFECT_INDEX_0; i <= EFFECT_INDEX_2; ++i)
                if (Effect[i] == effect)
                {
                    return true;
                }
            return false;
        }
        unsigned int GetTalentSpellCost(TalentSpellPos const* pos) const;
        unsigned int GetTalentSpellCost() const;
        SpellCastResult GetErrorAtShapeshiftedCast(unsigned int form) const;
    private:
#if 0
        // prevent creating custom entries (copy data from original in fact)
        SpellEntry(SpellEntry const&);                      // DON'T must have implementation
#endif
    };

    class SpellCastTimesEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    ID = 0;                                           // 0        m_ID
        int     CastTime = 0;                                     // 1        m_base
        // float     CastTimePerLevel;                          // 2        m_perLevel
        // int     MinCastTime;                               // 3        m_minimum
    };

    class SpellRadiusEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    ID = 0;                                           //          m_ID
        float     Radius = 0;                                       //          m_radius
        //          m_radiusPerLevel
        // float     RadiusMax;                                 //          m_radiusMax
    };

    class SpellRangeEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    ID = 0;                                           // 0        m_ID
        float     minRange = 0;                                     // 1        m_rangeMin
        float     maxRange = 0;                                     // 2        m_rangeMax
        // unsigned int  Flags;                                       // 3        m_flags
        // char*  Name[8];                                      // 4-11     m_displayName_lang
        // unsigned int NameFlags;                                    // 12 string flags
        // char*  ShortName[8];                                 // 13-20    m_displayNameShort_lang
        // unsigned int NameFlags;                                    // 21 string flags
    };

    class SpellShapeshiftFormEntry : public cftc::reflect::Object, public cftf::meta::Table<SpellShapeshiftFormEntry, unsigned int>
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int ID = 0;                                              // 0        m_ID
        // unsigned int buttonPosition;                               // 1        m_bonusActionBar
        // char*  Name[8];                                      // 2-9      m_name_lang
        // unsigned int NameFlags;                                    // 10 string flags
        unsigned int flags1 = 0;                                          // 11       m_flags
        int  creatureType = 0;                                    // 12       m_creatureType <=0 humanoid, other normal creature types
        // unsigned int unk1;                                         // 13       m_attackIconID
    };

    class SpellDurationEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    ID = 0;                                           //          m_ID
        int     Duration[3] = {0};                                  //          m_duration, m_durationPerLevel, m_maxDuration
    };

   class SpellFocusObjectEntry : public cftc::reflect::Object
    {
        CFT_DECLARE_REFLECT_CLASS();
    public:
        unsigned int    ID = 0;                                           // 0        m_ID
        // char*     Name[8];                                   // 1-8      m_name_lang
        // 9 string flags
    };

   class SpellItemEnchantmentEntry : public cftc::reflect::Object
   {
       CFT_DECLARE_REFLECT_CLASS();
   public:
       unsigned int      ID = 0;                                         // 0        m_ID
       unsigned int      type[3] = {0};                                    // 1-3      m_effect[3]
       unsigned int      amount[3] = {0};                                  // 4-6      m_effectPointsMin[3]
       // unsigned int      amount2[3]                               // 7-9      m_effectPointsMax[3]
       unsigned int      spellid[3] = {0};                                 // 10-12    m_effectArg[3]
       char* description[8] = {0};                             // 13-20    m_name_lang[8]
       // 21 string flags
       unsigned int      aura_id = 0;                                    // 22       m_itemVisual
       unsigned int      slot = 0;                                       // 23       m_flags
   };

   class StableSlotPricesEntry : public cftc::reflect::Object
   {
       CFT_DECLARE_REFLECT_CLASS();
   public:
       unsigned int Slot = 0;                                            //          m_ID
       unsigned int Price = 0;                                           //          m_cost
   };

#define MAX_TALENT_RANK 5

   /**
   * \struct TalentEntry
   * \brief Entry representing the talent tree and the links between each of them (conditions, ..)
   */
   class TalentEntry : public cftc::reflect::Object, public cftf::meta::Table<TalentEntry, unsigned int>
   {
       CFT_DECLARE_REFLECT_CLASS();
   public:

   public:
       unsigned int    TalentID = 0;                                     // 0        m_ID
       unsigned int    TalentTab = 0;                                    // 1        m_tabID (TalentTab.dbc)
       unsigned int    Row = 0;                                          // 2        m_tierID
       unsigned int    Col = 0;                                          // 3        m_columnIndex
       //unsigned int    RankID[MAX_TALENT_RANK] = {0};                      // 4-8      m_spellRank
       std::vector<unsigned int>   RankID;                      // 4-8      m_spellRank
       // 9-12 part of prev field
       unsigned int    DependsOn = 0;                                    // 13       m_prereqTalent (Talent.dbc)
       // 14-15 part of prev field
       unsigned int    DependsOnRank = 0;                                // 16       m_prereqRank
       // 17-18 part of prev field
       // unsigned int  needAddInSpellBook;                          // 19       m_flags also need disable higest ranks on reset talent tree
       unsigned int    DependsOnSpell = 0;                               // 20       m_requiredSpellID req.spell


       void MetaInstanceInit1();
       static TalentSpellPos const* GetTalentSpellPos(unsigned int spell_id);
   private:
       inline static std::map<unsigned int, TalentSpellPos> talent_spell_pos_map_;
   };

   class TalentTabEntry : public cftc::reflect::Object
   {
       CFT_DECLARE_REFLECT_CLASS();
   public:
       unsigned int  TalentTabID = 0;                                    // 0        m_ID
       // char* name[8];                                       // 1-8      m_name_lang
       // unsigned int  nameFlags;                                   // 9 string flags
       // unit32  spellicon;                                   // 10       m_spellIconID
       // 11       m_raceMask
       unsigned int  ClassMask = 0;                                      // 12       m_classMask
       unsigned int  tabpage = 0;                                        // 13       m_orderIndex
       // char* internalname;                                  // 14       m_backgroundFile
   };

   class TaxiNodesEntry : public cftc::reflect::Object, public cftf::meta::Table<TaxiNodesEntry, unsigned int>
   {
       CFT_DECLARE_REFLECT_CLASS();
   public:
       unsigned int    ID = 0;                                           // 0        ID - ID of the Taxi Node in DBC.
       unsigned int    map_id = 0;                                       // 1        m_ContinentID - ID of the Continent in DBC (0 = Azeroth, 1 = Kalimdor, 30 = Alterac Valley)
       float     x = 0;                                            // 2        m_x - X position of the Taxi Node.
       float     y = 0;                                            // 3        m_y - Y position of the Taxi Node.
       float     z = 0;                                            // 4        m_z - Z position of the Taxi Node.
       std::vector<std::string> name;                                      // 5-12     m_Name_lang - Name of the Taxi Node (relies on locale).
       // 13 string flags
       std::vector<unsigned int>    MountCreatureID;                           // 14-15    m_MountCreatureID[2] - Creature ID (indicates as well the Taxi Node type : horde[14]-alliance[15])
   };

   class TaxiPathEntry : public cftc::reflect::Object
   {
       CFT_DECLARE_REFLECT_CLASS();
   public:
       unsigned int    ID = 0;                                            // 0        ID - ID of the Taxi Path in DBC.
       unsigned int    from = 0;                                          // 1        m_from - ID of the Starting Taxi Node of the travel.
       unsigned int    to = 0;                                            // 2        m_to - ID of the Ending Taxi Node of the travel.
       unsigned int    price = 0;                                         // 3        m_price - Basic Price of the travel (Unit : Copper).
   };

   class TaxiPathNodeEntry : public cftc::reflect::Object
   {
       CFT_DECLARE_REFLECT_CLASS();
   public:
       // 0        m_ID - ID in the DBC.
       unsigned int    path = 0;                                         // 1        m_PathID - ID of the path in the DBC.
       unsigned int    index = 0;                                        // 2        m_NodeIndex - Index of the Node in the path.
       unsigned int    mapid = 0;                                        // 3        m_ContinentID - ID of the Continent in DBC (0 = Azeroth, 1 = Kalimdor, 30 = Alterac Valley)
       float     x = 0;                                            // 4        m_LocX - X position of the Node.
       float     y = 0;                                            // 5        m_LocY - Y position of the Node.
       float     z = 0;                                            // 6        m_LocZ - Z position of the Node.
       unsigned int    actionFlag = 0;                                   // 7        m_flags - Unknown usage.
       unsigned int    delay = 0;                                        // 8        m_delay - Unknown usage.
   };

   class WMOAreaTableEntry : public cftc::reflect::Object
   {
       CFT_DECLARE_REFLECT_CLASS();
   public:
       unsigned int Id = 0;                                              // 0        m_ID index
       int rootId = 0;                                           // 1        m_WMOID used in root WMO
       int adtId = 0;                                            // 2        m_NameSetID used in adt file
       int groupId = 0;                                          // 3        m_WMOGroupID used in group WMO
       // unsigned int field4;                                       // 4        m_SoundProviderPref
       // unsigned int field5;                                       // 5        m_SoundProviderPrefUnderwater
       // unsigned int field6;                                       // 6        m_AmbienceID
       // unsigned int field7;                                       // 7        m_ZoneMusic
       // unsigned int field8;                                       // 8        m_IntroSound
       unsigned int Flags = 0;                                           // 9        m_flags (used for indoor/outdoor determination)
       unsigned int areaId = 0;                                          // 10       m_AreaTableID (AreaTable.dbc)
       // char *Name[8];                                       //          m_AreaName_lang
       // unsigned int nameFlags;
   };

   class WorldMapAreaEntry : public cftc::reflect::Object
   {
       CFT_DECLARE_REFLECT_CLASS();
   public:
       // unsigned int  ID;                                          // 0        m_ID
       unsigned int  map_id = 0;                                         // 1        m_mapID
       unsigned int  area_id = 0;                                        // 2        m_areaID index (continent 0 areas ignored)
       // char* internal_name                                  // 3        m_areaName
       float   y1 = 0;                                             // 4        m_locLeft
       float   y2 = 0;                                             // 5        m_locRight
       float   x1 = 0;                                             // 6        m_locTop
       float   x2 = 0;                                             // 7        m_locBottom
   };

   class WorldSafeLocsEntry : public cftc::reflect::Object
   {
       CFT_DECLARE_REFLECT_CLASS();
   public:
       unsigned int    ID = 0;                                           // 0        m_ID
       unsigned int    map_id = 0;                                       // 1        m_continent
       float     x = 0;                                            // 2        m_locX
       float     y = 0;                                            // 3        m_locY
       float     z = 0;                                            // 4        m_locZ
       // char*   name[8]                                      // 5-12     m_AreaName_lang
       // 13 string flags
   };

}